# 此模块负责墙体参数的读取及一维墙体网格的离散
import numpy as np
import xlrd
'''
该模块负责对构建的墙体模型进行参数赋值与
模型离散
'''

# 定义‘墙’这个类别
class Wall:
    # 设置默认参数（名称，长，宽，高，顶点坐标值）
    def __init__(self, name, length=0):
        # 传递名称参数并得到其相关系数
        self.name = name
        # 设置长宽高，默认都为零
        self.length = length

        # 默认网格数量为（1,1,1）（x,y,z方向）
        self.grid = 1
        # 计算墙体各方向的步长
        self.step = self.length / self.grid

        self.coefficient = np.empty([])

    # 设置墙体名称
    def set_name(self, name):
        self.name = name

    # 设置墙体的形状
    def set_size(self, length=0):
        self.length = length

    # 设置墙体的热传导、湿传导系数-----------------------------------待完善
    def set_coefficient(self):
        excel = xlrd.open_workbook('materials/materials.xlsx')
        table = excel.sheet_by_name('coefficient')
        metarial_list = table.col_values(1)
        row_x = metarial_list.index(self.name)
        coefficient_values = table.row_values(row_x, 2)
        self.coefficient = np.array(coefficient_values, dtype=float)

    # 设置墙体网格数量（整数）
    def set_grid(self, grid=1):
        self.grid = int(grid)  # 网格取整
        self.step = self.length / self.grid  # 重新计算墙体各方向的步长

    # 设置墙体的步长，保证网格数量为整数
    def set_step(self, step):
        self.grid = int(self.length / step)  # 计算各方向的网格数量，取整
        self.step = self.length / self.grid  # 网格取整后，重新计算墙体各方向的步长

    def print_attribute(self):
        # 所有属性集合
        attribute = {'name': self.name,
                     'size': self.length,
                     'coefficient': self.coefficient,
                     'grid': self.grid,
                     'step': self.step}
        print(attribute)


# 按网格数量将墙体进行离散，得到各离散点的系数
def scatter_coefficient(coefficient, grid):
    s_coe = np.empty([])  # 申明变量s_coe，即离散点系数矩阵

    if type(coefficient) in [int, float]:  # 当输入参数类型为‘整型’或‘浮点型’时，进行单个离散
        s_coe = np.linspace(coefficient, coefficient, grid, dtype=float)

    elif type(coefficient) in [np.ndarray, list]:  # 当输入参数类型为‘数组’或‘列表’时，进行逐个离散
        s_coe = np.linspace(coefficient[0], coefficient[0], grid, dtype=float)
        for i in range(1, len(coefficient)):
            a = np.linspace(coefficient[i], coefficient[i], grid, dtype=float)
            s_coe = np.row_stack([s_coe, a])  # 得到二维系数与离散点的分布矩阵
    return s_coe  # 返回离散点的系数


# 创建墙体并进行离散
def create_wall(name, length, x_step):
    wall = Wall(name, length)
    wall.set_step(x_step)
    wall.set_coefficient()
    s_coe = scatter_coefficient(wall.coefficient, wall.grid)
    return s_coe


def create_walls(name: list, length: list, grid: list):
    # 设置墙体层数、名称、厚度及各层步长
    layersName = np.array(name)                 # 各材料名称
    layersLength = np.array(length)             # 各层材料厚度
    layersGrid = np.array(grid, dtype=int)      # 各层材料的计算网格数

    layers = len(layersName)                        # 墙体材料层数
    layersStep = layersLength / layersGrid          # 计算各层材料的步长

    x_step = layersStep.repeat(layersGrid)          # 得到步长矩阵

    # 创建多层墙体，返回墙体参数
    s_coe = [[]] * layers       # 创建墙体材料层数的空列表
    for n in range(layers):
        s_coe[n] = create_wall(layersName[n], layersLength[n], layersStep[n])  # 创建第n个墙体

    # 合并墙体参数
    # 当墙体为单层时
    s_coe_all = s_coe[0]       # 总参数等于第一个参数
    # 当墙体为多层时，进行叠加
    if layers > 1:
        for n in range(layers - 1):
            s_coe_all = np.hstack((s_coe_all, s_coe[n + 1]))

    return s_coe_all, x_step


if __name__ == '__main__':
    x_step = 100
    s_coe_1 = create_wall('PU', 100, x_step)
    s_coe_2 = create_wall('Clay brick', 200, x_step)
    s_coe_all = np.hstack((s_coe_1, s_coe_2))

    print(s_coe_all)
